package game.module.ddz.logic;

import java.lang.ref.WeakReference;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import game.module.ddz.DdzConstants;

public class DdzAlgorithm {

	private static Logger logger = LoggerFactory.getLogger(DdzAlgorithm.class);

	static class SingletonHolder {
		static DdzAlgorithm instance = new DdzAlgorithm();
	}

	public static DdzAlgorithm getInstance() {
		return SingletonHolder.instance;
	}

	public byte GetCardType(byte[] cbCardData, byte cbCardCount) {
		// 简单牌型
		switch (cbCardCount) {
		case 0: // 空牌
		{
			return DdzConstants.CT_ERROR;
		}
		case 1: // 单牌
		{
			return DdzConstants.CT_SINGLE;
		}
		case 2: // 对牌火箭
		{
			// 牌型判断
			if ((cbCardData[0] == 0x4F) && (cbCardData[1] == 0x4E))
				return DdzConstants.CT_MISSILE_CARD;
			if (GetCardLogicValue(cbCardData[0]) == GetCardLogicValue(cbCardData[1]))
				return DdzConstants.CT_DOUBLE;

			return DdzConstants.CT_ERROR;
		}
		}

		// 分析扑克
		WeakReference<TagAnalyseResult> tagAnalyseResultRef = new WeakReference<TagAnalyseResult>(
				new TagAnalyseResult());
		TagAnalyseResult tagAnalyseResult = tagAnalyseResultRef.get();
		AnalysebCardData(cbCardData, cbCardCount, tagAnalyseResult);

		// 四牌判断
		if (tagAnalyseResult.cbBlockCount[3] > 0) {
			// 牌型判断
			if ((tagAnalyseResult.cbBlockCount[3] == 1) && (cbCardCount == 4))
				return DdzConstants.CT_BOMB_CARD;
			if ((tagAnalyseResult.cbBlockCount[3] == 1) && (cbCardCount == 6))
				return DdzConstants.CT_FOUR_TAKE_ONE;
			if ((tagAnalyseResult.cbBlockCount[3] == 1) && (cbCardCount == 8)
					&& (tagAnalyseResult.cbBlockCount[1] == 2))
				return DdzConstants.CT_FOUR_TAKE_TWO;

			return DdzConstants.CT_ERROR;
		}

		// 三牌判断
		byte cbCardData1 = 0;
		if (tagAnalyseResult.cbBlockCount[2] > 0) {
			// 连牌判断
			if (tagAnalyseResult.cbBlockCount[2] > 1) {
				// 变量定义
				cbCardData1 = tagAnalyseResult.cbCardData[2][0];
				byte cbFirstLogicValue = GetCardLogicValue(cbCardData1);

				// 错误过虑
				if (cbFirstLogicValue >= 15)
					return DdzConstants.CT_ERROR;

				// 连牌判断
				for (byte i = 1; i < tagAnalyseResult.cbBlockCount[2]; i++) {
					cbCardData1 = tagAnalyseResult.cbCardData[2][i * 3];
					if (cbFirstLogicValue != (GetCardLogicValue(cbCardData1) + i))
						return DdzConstants.CT_ERROR;
				}
			} else if (cbCardCount == 3)
				return DdzConstants.CT_THREE;

			// 牌形判断
			if (tagAnalyseResult.cbBlockCount[2] * 3 == cbCardCount)
				return DdzConstants.CT_THREE_LINE;
			if (tagAnalyseResult.cbBlockCount[2] * 4 == cbCardCount)
				return DdzConstants.CT_THREE_TAKE_ONE;
			if ((tagAnalyseResult.cbBlockCount[2] * 5 == cbCardCount)
					&& (tagAnalyseResult.cbBlockCount[1] == tagAnalyseResult.cbBlockCount[2]))
				return DdzConstants.CT_THREE_TAKE_TWO;

			return DdzConstants.CT_ERROR;
		}

		// 两张类型
		if (tagAnalyseResult.cbBlockCount[1] >= 3) {
			// 变量定义
			cbCardData1 = tagAnalyseResult.cbCardData[1][0];
			byte cbFirstLogicValue = GetCardLogicValue(cbCardData1);

			// 错误过虑
			if (cbFirstLogicValue >= 15)
				return DdzConstants.CT_ERROR;

			// 连牌判断
			for (byte i = 1; i < tagAnalyseResult.cbBlockCount[1]; i++) {
				cbCardData1 = tagAnalyseResult.cbCardData[1][i * 2];
				if (cbFirstLogicValue != (GetCardLogicValue(cbCardData1) + i))
					return DdzConstants.CT_ERROR;
			}

			// 二连判断
			if ((tagAnalyseResult.cbBlockCount[1] * 2) == cbCardCount)
				return DdzConstants.CT_DOUBLE_LINE;

			return DdzConstants.CT_ERROR;
		}

		// 单张判断
		if ((tagAnalyseResult.cbBlockCount[0] >= 5) && (tagAnalyseResult.cbBlockCount[0] == cbCardCount)) {
			// 变量定义
			cbCardData1 = tagAnalyseResult.cbCardData[0][0];
			byte cbFirstLogicValue = GetCardLogicValue(cbCardData1);

			// 错误过虑
			if (cbFirstLogicValue >= 15)
				return DdzConstants.CT_ERROR;

			// 连牌判断
			for (byte i = 1; i < tagAnalyseResult.cbBlockCount[0]; i++) {
				cbCardData1 = tagAnalyseResult.cbCardData[0][i];
				if (cbFirstLogicValue != (GetCardLogicValue(cbCardData1) + i))
					return DdzConstants.CT_ERROR;
			}

			return DdzConstants.CT_SINGLE_LINE;
		}

		return DdzConstants.CT_ERROR;
	}

	// 分析扑克
	private void AnalysebCardData(byte cbCardData[], byte cbCardCount, TagAnalyseResult tagAnalyseResult) {
		// 扑克分析
		for (byte i = 0; i < cbCardCount; i++) {
			// 变量定义
			byte cbSameCount = 1, cbCardValueTemp = 0;
			byte cbLogicValue = GetCardLogicValue(cbCardData[i]);

			// 搜索同牌
			for (byte j = (byte) (i + 1); j < cbCardCount; j++) {
				// 获取扑克
				if (GetCardLogicValue(cbCardData[j]) != cbLogicValue)
					break;

				// 设置变量
				cbSameCount++;
			}

			// 设置结果
			byte cbIndex = tagAnalyseResult.cbBlockCount[cbSameCount - 1]++;
			for (byte j = 0; j < cbSameCount; j++)
				tagAnalyseResult.cbCardData[cbSameCount - 1][cbIndex * cbSameCount + j] = cbCardData[i + j];

			// 设置索引
			i += cbSameCount - 1;
		}
	}

	/**
	 * TODO 排列扑克，从大到小排序
	 * 
	 * @param cbCardData
	 * @param cbCardCount
	 * @param cbSortType
	 */
	public void SortCardList(byte[] cbCardData, byte cbCardCount, byte cbSortType) {
		// 数目过虑
		if (cbCardCount == 0)
			return;
		if (cbSortType == DdzConstants.ST_CUSTOM)
			return;

		// 转换数值
		byte[] cbSortValue = new byte[DdzConstants.MAX_COUNT];
		for (byte i = 0; i < cbCardCount; i++)
			cbSortValue[i] = GetCardLogicValue(cbCardData[i]);

		// 排序操作
		boolean bSorted = true;
		byte cbSwitchData = 0, cbLast = (byte) (cbCardCount - 1);
		do {
			bSorted = true;
			for (byte i = 0; i < cbLast; i++) {
				if ((cbSortValue[i] < cbSortValue[i + 1])
						|| ((cbSortValue[i] == cbSortValue[i + 1]) && (cbCardData[i] < cbCardData[i + 1]))) {
					// 设置标志
					bSorted = false;

					// 扑克数据
					cbSwitchData = cbCardData[i];
					cbCardData[i] = cbCardData[i + 1];
					cbCardData[i + 1] = cbSwitchData;

					// 排序权位
					cbSwitchData = cbSortValue[i];
					cbSortValue[i] = cbSortValue[i + 1];
					cbSortValue[i + 1] = cbSwitchData;
				}
			}
			cbLast--;
		} while (bSorted == false);

		// 数目排序
		if (cbSortType == DdzConstants.ST_COUNT) {
			// 变量定义
			byte cbCardIndex = 0;

			// 分析扑克
			WeakReference<TagAnalyseResult> tagAnalyseResultRef = new WeakReference<TagAnalyseResult>(
					new TagAnalyseResult());
			TagAnalyseResult tagAnalyseResult = tagAnalyseResultRef.get();
			AnalysebCardData(cbCardData, (byte) (cbCardCount - cbCardIndex), tagAnalyseResult);

			// 提取扑克
			for (byte i = 0; i < tagAnalyseResult.cbBlockCount.length; i++) {
				// 拷贝扑克
				byte cbIndex = (byte) (tagAnalyseResult.cbBlockCount.length - i - 1);
				// CopyMemory(&cbCardData[cbCardIndex],AnalyseResult.cbCardData[cbIndex],AnalyseResult.cbBlockCount[cbIndex]*(cbIndex+1)*sizeof(byte));

				// 设置索引
				cbCardIndex += tagAnalyseResult.cbBlockCount[cbIndex] * (cbIndex + 1) * 4;
			}
		}
	}

	// 对比扑克
	public boolean CompareCard(byte cbFirstCard[], byte cbNextCard[], byte cbFirstCount, byte cbNextCount) {
		// 获取类型
		byte cbNextType = GetCardType(cbNextCard, cbNextCount);
		byte cbFirstType = GetCardType(cbFirstCard, cbFirstCount);

		// 类型判断
		if (cbNextType == DdzConstants.CT_ERROR)
			return false;
		if (cbNextType == DdzConstants.CT_MISSILE_CARD)
			return true;

		// 炸弹判断
		if ((cbFirstType != DdzConstants.CT_BOMB_CARD) && (cbNextType == DdzConstants.CT_BOMB_CARD))
			return true;
		if ((cbFirstType == DdzConstants.CT_BOMB_CARD) && (cbNextType != DdzConstants.CT_BOMB_CARD))
			return false;

		// 规则判断
		if ((cbFirstType != cbNextType) || (cbFirstCount != cbNextCount))
			return false;

		// 开始对比
		switch (cbNextType) {
		case DdzConstants.CT_SINGLE:
		case DdzConstants.CT_DOUBLE:
		case DdzConstants.CT_THREE:
		case DdzConstants.CT_SINGLE_LINE:
		case DdzConstants.CT_DOUBLE_LINE:
		case DdzConstants.CT_THREE_LINE:
		case DdzConstants.CT_BOMB_CARD: {
			// 获取数值
			byte cbNextLogicValue = GetCardLogicValue(cbNextCard[0]);
			byte cbFirstLogicValue = GetCardLogicValue(cbFirstCard[0]);

			// 对比扑克
			return cbNextLogicValue > cbFirstLogicValue;
		}
		case DdzConstants.CT_THREE_TAKE_ONE:
		case DdzConstants.CT_THREE_TAKE_TWO: {
			// 分析扑克
			WeakReference<TagAnalyseResult> NextResultRef = new WeakReference<TagAnalyseResult>(new TagAnalyseResult());
			TagAnalyseResult NextResult = NextResultRef.get();
			WeakReference<TagAnalyseResult> FirstResultRef = new WeakReference<TagAnalyseResult>(
					new TagAnalyseResult());
			TagAnalyseResult FirstResult = FirstResultRef.get();
			AnalysebCardData(cbNextCard, cbNextCount, NextResult);
			AnalysebCardData(cbFirstCard, cbFirstCount, FirstResult);

			// 获取数值
			byte cbNextLogicValue = GetCardLogicValue(NextResult.cbCardData[2][0]);
			byte cbFirstLogicValue = GetCardLogicValue(FirstResult.cbCardData[2][0]);

			// 对比扑克
			return cbNextLogicValue > cbFirstLogicValue;
		}
		case DdzConstants.CT_FOUR_TAKE_ONE:
		case DdzConstants.CT_FOUR_TAKE_TWO: {
			// 分析扑克
			WeakReference<TagAnalyseResult> NextResultRef = new WeakReference<TagAnalyseResult>(new TagAnalyseResult());
			TagAnalyseResult NextResult = NextResultRef.get();
			WeakReference<TagAnalyseResult> FirstResultRef = new WeakReference<TagAnalyseResult>(
					new TagAnalyseResult());
			TagAnalyseResult FirstResult = FirstResultRef.get();
			AnalysebCardData(cbNextCard, cbNextCount, NextResult);
			AnalysebCardData(cbFirstCard, cbFirstCount, FirstResult);

			// 获取数值
			byte cbNextLogicValue = GetCardLogicValue(NextResult.cbCardData[3][0]);
			byte cbFirstLogicValue = GetCardLogicValue(FirstResult.cbCardData[3][0]);

			// 对比扑克
			return cbNextLogicValue > cbFirstLogicValue;
		}
		}

		return false;
	}

	// 逻辑数值
	public byte GetCardLogicValue(byte cbCardData) {
		// 扑克属性
		byte cbCardColor = GetCardColor(cbCardData);
		byte cbCardValue = GetCardValue(cbCardData);

		// 转换数值
		if (cbCardColor == 0x40)
			return (byte) (cbCardValue + 2);
		return (byte) ((cbCardValue <= 2) ? (cbCardValue + 13) : cbCardValue);
	}

	// 获取数值
	public byte GetCardValue(byte cbCardData) {
		return (byte) (cbCardData & DdzConstants.MASK_VALUE);
	}

	// 获取花色
	public byte GetCardColor(byte cbCardData) {
		return (byte) (cbCardData & DdzConstants.MASK_COLOR);
	}

	public static void main(String[] args) {
		DdzAlgorithm ddzAlgorithm = new DdzAlgorithm();
		// byte cardType = ddzAlgorithm.GetCardType(new byte[] { 0x08, 0x18,
		// 0x27, 0x37, 0x16, 0x26 }, (byte) 6);
		// System.out.println(cardType);
		byte[] toSortList = new byte[] { 0x34, 0x25, 0x0A, 0x18 };
		ddzAlgorithm.SortCardList(toSortList, (byte) toSortList.length, DdzConstants.ST_ORDER);
		logger.info("a={}",toSortList);
	}

}
